package com.oraclechain.pocketeos.blockchain;

import android.content.Context;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.oraclechain.pocketeos.base.Constants;
import com.oraclechain.pocketeos.bean.SendRedPacketBean;
import com.oraclechain.pocketeos.blockchain.api.EosChainInfo;
import com.oraclechain.pocketeos.blockchain.bean.JsonToBeanResultBean;
import com.oraclechain.pocketeos.blockchain.bean.JsonToBinRequest;
import com.oraclechain.pocketeos.blockchain.chain.Action;
import com.oraclechain.pocketeos.blockchain.chain.PackedTransaction;
import com.oraclechain.pocketeos.blockchain.chain.SignedTransaction;
import com.oraclechain.pocketeos.blockchain.cypto.ec.EosPrivateKey;
import com.oraclechain.pocketeos.blockchain.types.TypeChainId;
import com.oraclechain.pocketeos.blockchain.util.Consts;
import com.oraclechain.pocketeos.blockchain.util.GsonEosTypeAdapterFactory;
import com.oraclechain.pocketeos.coin.BaseCoin;
import com.trello.rxlifecycle2.LifecycleProvider;

import java.math.BigDecimal;
import java.util.ArrayList;

import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import plugin.eos.awake.flutter.awake1.network.ApiService;
import plugin.eos.awake.flutter.awake1.network.MySubscriber;
import plugin.eos.awake.flutter.awake1.network.RetrofitManager;

public class CommonDataManager {
	//原力手续费
	public final static int TRANSFER_YUANLI_FEE = 100;
	public final static int CLAIM_FEE = 300;
	public final static int VOTE_FEE = 500;
	public final static int REVOTE_FEE = 2000;
	public final static int VOTEFIX_FEE = 5000;        // 定投手续费
	public final static int REVOTEFIX_FEE = 7500;       // 定期转投手续费
	/**
	 * 创建账号手续费
	 */
	public final static int CREATE_FEE = 1000;
	public final static int TRANSFER_UNFEEZE = 100;

	public static WalletAccountType sCurrentWalletType;
	public static int sFeeAmount;


	private static String PERMISSONION = Constants.PERMISSONION;
	private Context mContext;
	private EosChainInfo mChainInfoBean = new EosChainInfo();
	private JsonToBeanResultBean mJsonToBeanResultBean = new JsonToBeanResultBean();
	private String[] permissions;
	private SignedTransaction txnBeforeSign;
	private Gson mGson = new GsonBuilder()
			.registerTypeAdapterFactory(new GsonEosTypeAdapterFactory())
			.excludeFieldsWithoutExposeAnnotation().create();

	private String contract, action, message;
	private int type = 1; //0即为红包 ， 1为转账
	private SendRedPacketBean.DataBean redpacketInfo = new SendRedPacketBean.DataBean(); // 红包信息
	private String redpacketNumber = null;
	private BigDecimal coinRate;//资产汇率
	private CommonDataBean mCommonDataBean;
	private BaseCoin mCoin;
	private WalletAccountType mWalletAccountType;

	public CommonDataManager(Context context, CommonDataBean dataBean) {
		this(context, dataBean, dataBean.getBaseCoin().getContract(), dataBean.getBaseCoin().getWalletType());
	}

	public CommonDataManager(Context context, CommonDataBean dataBean, String contract, WalletAccountType walletAccountType) {
		mContext = context;
		mCommonDataBean = dataBean;
		mCoin = dataBean.getBaseCoin();
		this.contract = contract;
		this.action = mCommonDataBean.getAction();
		this.mWalletAccountType = walletAccountType;

		CommonDataManager.sCurrentWalletType = mWalletAccountType;
		CommonDataManager.sFeeAmount = mCommonDataBean.getFee();
	}

	public void pushAction(String data, String fromAccountName, String privateKey, LifecycleProvider mContext, AwakeRequestCallBack callBack) {
		this.message = data;
		this.type = 1;
		permissions = new String[]{fromAccountName + "@" + PERMISSONION};
		getChainInfo(privateKey, mContext, callBack);
	}

	private void getChainInfo(String privateKey, LifecycleProvider mContext, AwakeRequestCallBack callBack) {
		RetrofitManager.get(ApiService.class)
				.getEosChainInfo()
				.subscribeOn(Schedulers.io())
				.observeOn(AndroidSchedulers.mainThread())
				.compose(mContext.bindToLifecycle())
				.subscribe(new MySubscriber<EosChainInfo>("getEosChainInfo") {
					@Override
					protected void _onNext(EosChainInfo chainInfoBean) {
						mChainInfoBean = chainInfoBean;
						getabi_json_to_bin(privateKey, mContext, callBack);
					}

					@Override
					protected void _onError(Throwable e, String message) {
						callBack.error(e, message);
					}
				});

	}

	private void getabi_json_to_bin(String privateKey, LifecycleProvider mContext, AwakeRequestCallBack callBack) {
		JsonToBinRequest jsonToBinRequest = new JsonToBinRequest(contract, action, message.replaceAll("\\r|\\n", ""));
		RetrofitManager.get(ApiService.class)
				.jsonToBin(jsonToBinRequest)
				.subscribeOn(Schedulers.io())
				.observeOn(AndroidSchedulers.mainThread())
				.compose(mContext.bindToLifecycle())
				.subscribe(new MySubscriber<JsonToBeanResultBean>("jsonToBin") {
					@Override
					protected void _onNext(JsonToBeanResultBean chainInfoBean) {
						mJsonToBeanResultBean = chainInfoBean;
						txnBeforeSign = createTransaction(contract, action, mJsonToBeanResultBean.getBinargs(), permissions, mChainInfoBean);

						EosPrivateKey eosPrivateKey = new EosPrivateKey(privateKey, mWalletAccountType);
						txnBeforeSign.sign(eosPrivateKey, new TypeChainId(mChainInfoBean.getChain_id()), mCoin.getWalletType());
						pushTransactionRetJson(new PackedTransaction(txnBeforeSign), mContext, callBack);

					}

					@Override
					protected void _onError(Throwable e, String message) {
						callBack.error(e, message);
					}
				});
	}

	private SignedTransaction createTransaction(String contract, String actionName, String dataAsHex,
	                                            String[] permissions, EosChainInfo chainInfo) {

		Action action = new Action(contract, actionName);
		action.setAuthorization(permissions);
		action.setData(dataAsHex);

		SignedTransaction txn = new SignedTransaction();
		txn.addAction(action);
		txn.putSignatures(new ArrayList<>());


		if (null != chainInfo) {
			txn.setReferenceBlock(chainInfo.getHeadBlockId());
			txn.setExpiration(chainInfo.getTimeAfterHeadBlockTime(Consts.TX_EXPIRATION_IN_MILSEC));
		}
		return txn;
	}

	private void pushTransactionRetJson(PackedTransaction body, LifecycleProvider mContext, AwakeRequestCallBack callBack) {
		RetrofitManager.get(ApiService.class)
				.pushTransactionRetJson(body)
				.subscribeOn(Schedulers.io())
				.observeOn(AndroidSchedulers.mainThread())
				.compose(mContext.bindToLifecycle())
				.subscribe(new MySubscriber<JsonObject>("pushTransactionRetJson") {
					@Override
					protected void _onNext(JsonObject chainInfoBean) {
						callBack.success();
					}

					@Override
					protected void _onError(Throwable e, String message) {
						callBack.error(e, message);
					}
				});

	}

}
